/*
 * 项   目：code-generator
 * 作   者：LuoYiMin
 * 邮   箱：1725990142@qq.com
 * 创建时间：2018/12/27 9:38
 */
package com.roin.util.code.generator.controller;

import com.roin.util.code.generator.DefaultConfig;
import com.roin.util.code.generator.model.GeneratorConfig;
import com.roin.util.code.generator.util.ConfigHelper;
import com.roin.util.code.generator.util.FreemarkerManager;
import com.roin.util.code.generator.util.StringUtils;
import com.roin.util.code.generator.view.AlertUtil;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;

public class MainFrameController extends BaseController{

    private static final Logger LOGGER = LoggerFactory.getLogger(MainFrameController.class);

    @FXML
    private TextField projectFolderField;
    @FXML
    private TextField htmlFolderField;
    @FXML
    private TextField controllerTargetProject;
    @FXML
    private TextField serviceTargetProject;
    @FXML
    private TextField controllerPackageField;
    @FXML
    private TextField servicePackageField;
    @FXML
    private TextField modelFullNameField;
    @FXML
    private TextField daoFullNameField;
    @FXML
    private TextField moduleField;
    @FXML
    private TextField authorField;
    @FXML
    private CheckBox htmlCheckBox;
    @FXML
    private CheckBox controllerCheckBox;
    @FXML
    private CheckBox serviceCheckBox;
    @FXML
    private ComboBox configComboBox;
    @FXML
    private Button htmlConfigButton;
    @FXML
    private Button controllerConfigButton;

    private GeneratorConfig generatorConfig = new GeneratorConfig();


    /**
     * 初始化设置方法
     * @param location
     * @param resources
     */
    public void initialize(URL location, ResourceBundle resources) {
        try {
            List<String> configs = ConfigHelper.loadGeneratorConfigNames();
            configComboBox.setItems(FXCollections.observableList(configs));
            configComboBox.getSelectionModel().selectedItemProperty().addListener((ChangeListener<String>) (observable, oldValue, newValue) -> {
                try {
                    if (newValue==null)
                        return;
                    generatorConfig = ConfigHelper.loadGeneratorConfig(newValue);
                    resetConfig();
                } catch (Exception e) {
                   LOGGER.error("加载配置"+newValue+"异常",e);
                }
            });

            htmlCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
                htmlFolderField.setEditable(newValue);
                htmlConfigButton.setDisable(!newValue);
            });
            controllerCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
                controllerPackageField.setEditable(newValue);
                controllerConfigButton.setDisable(!newValue);
            });

        } catch (Exception e) {
            AlertUtil.showErrorAlert(e.getMessage());
        }

        htmlCheckBox.setTooltip(new Tooltip("是否生成Html代码"));
        controllerCheckBox.setTooltip(new Tooltip("是否要生成Controller代码"));
        serviceCheckBox.setTooltip(new Tooltip("是否要生成Service代码"));
    }
    private void resetConfig(){
        projectFolderField.setText(generatorConfig.getProjectFolder());
        htmlFolderField.setText(generatorConfig.getHtmlFolder());
        controllerTargetProject.setText(generatorConfig.getControllerTargetProject());
        controllerPackageField.setText(generatorConfig.getControllerPackage());
        servicePackageField.setText(generatorConfig.getServicePackage());
        serviceTargetProject.setText(generatorConfig.getServiceTargetProject());
        daoFullNameField.setText(generatorConfig.getServiceConfig().getMapperFullName());
        modelFullNameField.setText(generatorConfig.getModelFullName());
        moduleField.setText(generatorConfig.getModule());
        authorField.setText(generatorConfig.getAuthor());
        htmlCheckBox.setSelected(generatorConfig.isHtml());
        controllerCheckBox.setSelected(generatorConfig.isController());
        serviceCheckBox.setSelected(generatorConfig.isService());
    }

    /**
     * 项目目录选择事件
     */
    @FXML
    public void chooseProjectFolder() {
        showFolderChooseDialog(projectFolderField);
    }
    /**
     * HTML目录选择事件
     */
    @FXML
    public void chooseHtmlFolder() {
        showFolderChooseDialog(htmlFolderField);
    }

    private void showFolderChooseDialog(TextField textField) {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        String path = textField.getText();
        if (!StringUtils.isEmpty(path)){
            File file = new File(path);
            if (file.exists())
                directoryChooser.setInitialDirectory(file);
        }
        File selectedFolder = directoryChooser.showDialog(getPrimaryStage());
        if (selectedFolder != null) {
            textField.setText(selectedFolder.getAbsolutePath());
        }
    }

    /**
     * 生成代码按钮事件处理器
     */
    @FXML
    public void generateCode(){
        resetGeneratorConfigFromUI();
        String filePath;
        try {
            if (generatorConfig.isController()){
                filePath = generatorConfig.getProjectFolder()+File.separator+generatorConfig.getControllerTargetProject()+File.separator+
                        generatorConfig.getControllerPackage().replace(".",File.separator);
                if (!checkFile(filePath)){
                    return;
                }
                //生成Controller类
                FreemarkerManager.outToFile(DefaultConfig.getControllerTemplateName(),generatorConfig,filePath+File.separator+generatorConfig.getModelName()+"Controller.java");
                LOGGER.info("生成Controller成功！");
            }
        }catch (Exception e){
            LOGGER.error("生成Controller异常",e);
        }
        try {
            if (generatorConfig.isService()) {
                filePath = generatorConfig.getProjectFolder() + File.separator + generatorConfig.getServiceTargetProject() + File.separator +
                        generatorConfig.getServicePackage().replace(".", File.separator);
                if (!checkFile(filePath)) {
                    return;
                }
                //生成Service接口
                FreemarkerManager.outToFile(DefaultConfig.getServiceTemplateName(),generatorConfig,filePath+File.separator+generatorConfig.getModelName()+"Service.java");
                filePath =generatorConfig.getProjectFolder()+File.separator+generatorConfig.getServiceTargetProject()+File.separator+
                        generatorConfig.getServicePackage().replace(".",File.separator)+File.separator+"impl"+File.separator;
                if (!checkFile(filePath)){
                    return;
                }
                //生成Service实现类
                FreemarkerManager.outToFile(DefaultConfig.getServiceImplTemplateName(),generatorConfig,filePath+File.separator+generatorConfig.getModelName()+"ServiceImpl.java");
                LOGGER.info("生成Service成功！");
            }
        }catch (Exception e){
            LOGGER.error("生成Service异常",e);
        }

        try {
            if (generatorConfig.isHtml()){
                filePath = generatorConfig.getHtmlFolder() + File.separator + generatorConfig.getModelSnakeName();
                if (!checkFile(filePath)) {
                    return;
                }
                //生成Html实现类
                FreemarkerManager.outToFile(DefaultConfig.getHtmlTemplateName(),generatorConfig,filePath+File.separator+"list.html");
                if (generatorConfig.getHtmlConfig().isNeedAddForm() || generatorConfig.getHtmlConfig().isNeedEditForm()){
                    //生成Add表单
                    FreemarkerManager.outToFile(DefaultConfig.getHtmlAddTemplateName(),generatorConfig,filePath+File.separator+"add.html");
                }
                LOGGER.info("生成Html成功！");
            }
        }catch (Exception e){
            LOGGER.error("生成Html异常",e);
        }


        AlertUtil.showInfoAlert("生成代码完成！若部分代码未生成，请查看日志文件logs/error.log 。");

    }
    private boolean checkFile(String filePath){
        File file = new File(filePath);
        if (!file.exists()){
            Alert alert = AlertUtil.buildConfirmationAlert("路径：" + filePath + "不存在，是否创建目录？");
            Optional<ButtonType> optional= alert.showAndWait();
            if (optional.isPresent() && optional.get().getButtonData()== ButtonBar.ButtonData.OK_DONE){
                file.mkdirs();
            }else {
                return false;
            }
        }
        if (!file.isDirectory()) {
            AlertUtil.showErrorAlert("路径：" + filePath + "不是一个目录，请检查！");
            return false;
        }
        return true;
    }

    /**
     * 打开Html配置窗口
     */
    @FXML
    public void openHtmlConfigFrame(){
        HtmlConfigController controller = (HtmlConfigController) loadFXMLPage("Html配置", FXMLPage.HTML_CONFIG, true);
        controller.showDialogStage();
        controller.setConfig(generatorConfig.getHtmlConfig());
    }
    /**
     * 打开Controller配置窗口
     */
    @FXML
    public void openControllerConfigFrame(){
        ControllerConfigController controller = (ControllerConfigController) loadFXMLPage("Controller配置", FXMLPage.CONTROLLER_CONFIG, true);
        controller.setConfig(generatorConfig.getControllerConfig());
        controller.showDialogStage();
    }
    /**
     * 打开代码生成目录
     */
    @FXML
    public void openGenerateCodeDir(){
        String projectDir = projectFolderField.getText();
        try {
            Desktop.getDesktop().browse(new File(projectDir).toURI());
        } catch (IOException e) {
            AlertUtil.showErrorAlert("打开目录失败，请检查目录是否填写正确!");
            LOGGER.error("打开代码生成目录异常",e);
        }
    }

    /**
     * 保存配置
     */
    @FXML
    public void saveConfig(){
        String validResult = validateConfig();
        if (validResult!=null){
            AlertUtil.showWarnAlert(validResult);
           return;
        }
        TextInputDialog dialog = new TextInputDialog(generatorConfig.getName());
        dialog.setTitle("保存当前配置");
        dialog.setHeaderText("请输入配置名称");
        Optional<String> result = dialog.showAndWait();
        if (result.isPresent()) {
            String name = result.get();
            if (StringUtils.isEmpty(name)) {
                AlertUtil.showErrorAlert("名称不能为空");
                return;
            }
            LOGGER.info("user choose name: {}", name);
            try {
                resetGeneratorConfigFromUI();
                generatorConfig.setName(name);
                ConfigHelper.saveOrUpdateGeneratorConfig(generatorConfig);
                //刷新配置下拉框
                List<String> configs = ConfigHelper.loadGeneratorConfigNames();
                configComboBox.setItems(FXCollections.observableList(configs));
            } catch (Exception e) {
                AlertUtil.showErrorAlert("保存配置失败");
                LOGGER.error("保存配置失败",e);
            }
        }

    }

    /**
     * 保存配置前检查数据
     * @return
     */
    private String validateConfig() {
        String projectFolder = projectFolderField.getText();
        if (StringUtils.isEmpty(projectFolder))  {
            return "项目目录不能为空";
        }
        if (StringUtils.isEmpty(htmlFolderField.getText()))  {
            return "Html目录不能为空";
        }
        if (StringUtils.isAnyEmpty(controllerPackageField.getText(), servicePackageField.getText())) {
            return "包名不能为空";
        }
        if (!htmlCheckBox.isSelected() && !controllerCheckBox.isSelected() && !serviceCheckBox.isSelected()) {
            return "必须选择一个要生成的代码";
        }
        return null;
    }

    /**
     * 创建配置实例
     * @return
     */
    private void resetGeneratorConfigFromUI(){
        String projectDir =  projectFolderField.getText();
        String htmlDir =  htmlFolderField.getText();
        String controllerTarget =  controllerTargetProject.getText();
        String serviceTarget =  serviceTargetProject.getText();
        String controllerPackage =  controllerPackageField.getText();
        String servicePackage =  servicePackageField.getText();
        String mapperFullName =  daoFullNameField.getText();
        String modelFullName =  modelFullNameField.getText();
        String module =  moduleField.getText();
        String author =  authorField.getText();
        boolean htmlChecked =  htmlCheckBox.isSelected();
        boolean controllerChecked =  controllerCheckBox.isSelected();
        boolean serviceChecked =  serviceCheckBox.isSelected();

        generatorConfig.setProjectFolder(projectDir);
        generatorConfig.setHtmlFolder(htmlDir);
        generatorConfig.setHtml(htmlChecked);
        generatorConfig.setControllerTargetProject(controllerTarget);
        generatorConfig.setServiceTargetProject(serviceTarget);
        generatorConfig.setControllerPackage(controllerPackage);
        generatorConfig.setController(controllerChecked);
        generatorConfig.setServicePackage(servicePackage);
        generatorConfig.getServiceConfig().setMapperFullName(mapperFullName);
        if (!StringUtils.isEmpty(mapperFullName)){
            generatorConfig.getServiceConfig().setMapperName(mapperFullName.substring(mapperFullName.lastIndexOf(".")+1));
            generatorConfig.getServiceConfig().setMapperPackage(mapperFullName.substring(0,mapperFullName.lastIndexOf(".")));
            if (generatorConfig.getServiceConfig().getMapperName()!=null){
                generatorConfig.getServiceConfig().setMapperHumpName(StringUtils.toLowerCaseFirstChar(generatorConfig.getServiceConfig().getMapperName()));
            }
        }
        generatorConfig.setService(serviceChecked);
        generatorConfig.setModelFullName(modelFullName);
        if (!StringUtils.isEmpty(modelFullName)){
            generatorConfig.setModelName(modelFullName.substring(modelFullName.lastIndexOf(".")+1));
            generatorConfig.setModelPackage(modelFullName.substring(0,modelFullName.lastIndexOf(".")));
            if (generatorConfig.getModelName()!=null){
                generatorConfig.setModelHumpName(StringUtils.toLowerCaseFirstChar(generatorConfig.getModelName()));
                generatorConfig.setModelSnakeName(StringUtils.humpToLine(generatorConfig.getModelName()));
            }
        }
        generatorConfig.setModule(module);
        generatorConfig.setAuthor(author);
    }
}
